﻿#include "rulebar.h"
#include <float.h>
#include <QGraphicsView>
#include <QBrush>
#include <QtMath>
#include <QDebug>

namespace eintik::presentation::viewcore {

#define MINIMUM_INCR 4
const int32_t maxGateCnt = 5;

typedef struct
{
    double ruler_scale[19];
    int subdivide[5];
    int reverse;
} SPRulerMetric;

// Ruler metric for general use.
static const SPRulerMetric ruler_metric_general = { { 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200,
                                                      500, 1000, 2000, 5000, 10000, 22000, 50000,
                                                      100000 },
                                                    { 1, 2, 10, 50, 100 }, 0};

const QTransform QRuleBar::gRotateForm90 = QTransform(0, 1, 0, -1, 0, 0, 0, 0, 1);
const QTransform QRuleBar::gRotateForm270 = QTransform(0, -1, 0, 1, 0, 0, 0, 0, 1);

QRuleBar::QRuleBar(QRulerPos direction, QRulerType type, QGraphicsView *view, QWidget *parent)
    : QWidget(parent)
    , m_view(view)
    , m_enable(false)
{
    m_lower = 0.0;
    m_upper = 100.0;
    m_maxsize = 2.0;
    m_lastPos.setX(100);
    m_lastPos.setY(100);
    m_direction = direction;
    m_show_direction = direction;
    m_type = type;
    switch (type) {
    case SoundPath_Ruler:
    case TOFD_Depth_Ruler:
        m_faceColor = QColor(0xB3, 0x25, 0xBD); // QColor(0x86, 0x1B, 0x8D);
        break;
    case Depth_Ruler:
        m_faceColor = QColor(0xB3, 0x25, 0xBD);
        break;
    case HDistance_Ruler:
        m_faceColor = QColor(0x1B, 0xA6, 0x60);
        break;
    case Height_Ruler:
        m_faceColor = QColor(0xC2, 0xD8, 0x14);
        break;
    case ColorBar_Ruler:
        m_faceColor = QColor(0xff, 0xff, 0xff);
        break;
    case Scan_Ruler:
        m_faceColor = QColor(0x1E, 0x90, 0xFF);
        break;
    default:
        m_faceColor = QColor(0xff, 0xff, 0xff);
        break;
    }

    m_unit.clear();

    colorMap.reserve(260);

    for (auto i = 1; i < maxGateCnt; i++) {
        m_GateEnable[i] = false;
        m_GateHeight[i] = 1;
        m_GateMark1[i] = 0;
        m_GateMark2[i] = 0;
    }

    this->hide();
}

QRuleBar::~QRuleBar() { }

void QRuleBar::setRange(double lower, double upper, double max_size)
{
    bool ret = false;
    if (std::fabs(m_lower - lower) > DBL_EPSILON ||
            std::fabs(m_upper - upper) > DBL_EPSILON ||
            std::fabs(m_maxsize - max_size) > DBL_EPSILON
            )
        ret = true;
    m_lower = lower;
    m_upper = upper;
    m_maxsize = max_size;

    if (ret)
        update(); //?????????????????
}

void QRuleBar::getRange(double &lower, double &upper, double &max_size)
{
    lower = m_lower;
    upper = m_upper;
    max_size = m_maxsize;
}

void QRuleBar::updatePosition(const QPoint &pos)
{
    if (m_enable) {
        m_lastPos = pos;
        update();
    }
}

double QRuleBar::getTofdDepth(double timeUs)
{
    double retVal = -1;
    getTofdDepth(timeUs, retVal);
    return retVal;
}

void QRuleBar::setRulerEnable(bool enable)
{
    m_enable = enable;
    if (m_enable)
        this->show();
    else
        this->hide();
}

void QRuleBar::setRulerPosition(QRulerPos pos)
{
    // m_direction = pos;
    m_show_direction = pos;
}

QRulerPos QRuleBar::getRulerPosition()
{
    return m_direction;
}

void QRuleBar::setRulerType(QRulerType type)
{
    m_type = type;
    // if ((type >= SoundPath_Ruler) && (type <= ColorBar_Ruler))
    //     m_enable = false;
    switch (type) {
    case SoundPath_Ruler:
    case TOFD_Depth_Ruler:
        m_faceColor = QColor(0xB3, 0x25, 0xBD); // QColor(0x86, 0x1B, 0x8D);
        break;
    case Depth_Ruler:
        m_faceColor = QColor(0xB3, 0x25, 0xBD);
        break;
    case HDistance_Ruler:
        m_faceColor = QColor(0x1B, 0xA6, 0x60);
        break;
    case Height_Ruler:
        m_faceColor = QColor(0xC2, 0xD8, 0x14);
        break;
    case ColorBar_Ruler:
        m_faceColor = QColor(0xff, 0xff, 0xff);
        break;
    case Scan_Ruler:
        m_faceColor = QColor(0x1E, 0x90, 0xFF);
        break;
    default:
        m_faceColor = QColor(0xff, 0xff, 0xff);
        break;
    }
}

void QRuleBar::setUnitStr(const QString &unit)
{
    m_unit = unit;
}

const QString QRuleBar::getUnitStr() const
{
    return m_unit;
}

bool QRuleBar::RulerEnable() const
{
    return m_enable;
}

void QRuleBar::setZoomEnable(bool e)
{
    this->zoomEnable = e;
    this->update();
}

bool QRuleBar::getZoomEnalbe()
{
    return zoomEnable;
}

void QRuleBar::setZoomValue(double v1, double v2)
{
    if (!zooming) {
        this->zoomStart = v1;
        this->zoomEnd = v1 + v2;
    }
}

void QRuleBar::getZoomValue(double &v1, double &v2)
{
    v1 = this->zoomStart / 1.0;
    v2 = (this->zoomEnd - this->zoomStart) / 1.0;
}

void QRuleBar::setBackGroudColor(QColor color)
{
    m_faceColor = color;
}

void QRuleBar::setColorMap(const QVector<QColor> &colorVector)
{
    colorMap = colorVector;
}

void QRuleBar::setGateEnable(int32_t GateId, bool enable)
{
    if (GateId < maxGateCnt)
        m_GateEnable[GateId] = enable;
}

void QRuleBar::setGateHeight(int32_t GateId, int32_t GateHeight)
{
    if (GateId < maxGateCnt)
        m_GateHeight[GateId] = GateHeight;
}

void QRuleBar::setGatePosition(int32_t GateId, double GateMark1, double GateMark2)
{
    if (GateId < maxGateCnt) {
        // GateMark1 GateMark2 可能超出100%哦
        m_GateMark1[GateId] = static_cast<int>(GateMark1 * 100.0);
        m_GateMark2[GateId] = static_cast<int>(GateMark2 * 100.0);
    }
}

void QRuleBar::setPieceVelocity(double velocity)
{
    this->pieceVelocity = velocity;
}

void QRuleBar::setPCS(double pcs, double t0)
{
    this->tofdPcs = pcs;
    this->wedgeDelay = t0;
}

void QRuleBar::setTransform(const QTransform &form)
{
    this->rotateForm = form;
}

void QRuleBar::setScanPath(bool r, double d)
{
    radian = r;
    if (r)
        diameter = d;

    this->update();
}

void QRuleBar::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    if (m_enable) {
        QPainter painter(this);
        QRect rulerRect = rect();

        if (m_type == ColorBar_Ruler) {
            painter.fillRect(rulerRect, QColor(75, 75, 75));
            QImage image(RULER_SIZE / 2, 256, QImage::Format_RGB32);
            if (colorMap.size() >= 256) {
                for (auto i = 0; i < 256; i++) {
                    uint32_t *pImage = reinterpret_cast<uint32_t *>(image.scanLine(i));
                    for (auto j = 0; j < RULER_SIZE / 2; j++) {
                        *pImage++ = colorMap[255 - i].rgb();
                    }
                }
            }
            image = image.transformed(rotateForm);
            rulerRect.adjust(1, 1, -1, -1);
            painter.drawImage(rulerRect, image);
        } else {
            if (m_type == TOFD_Depth_Ruler)
                drawTofdTicker(&painter);
            else
                drawTicker(&painter);
        }
    }
}

QString QRuleBar::getTickText(double cur, int scale, bool unit)
{
    QString tempText;
    if (m_type == Height_Ruler) {
        tempText.setNum(cur, 'f', 0);
    } else {
        int curInterger = static_cast<int>(cur);
        if (scale <= 2) {
            if (qAbs(curInterger) >= 2000000
                && ((curInterger) / 1000000) * 1000000 == (curInterger)) {
                // sprintf(unit_str, "%.1fm", (cur) / 1000000);
                tempText = QString("%1m").arg(cur, 0, 'f', 1);
            } else
                tempText = QString("%1").arg(cur, 0, 'f', 1);
        } else {
            if (qAbs(curInterger) >= 2000000
                && ((curInterger) / 1000000) * 1000000 == (curInterger))
                // sprintf(unit_str, "%dm", (curInterger) / 1000000);
                tempText = QString("%1m").arg(curInterger);
            else
                tempText = QString("%1").arg(curInterger);
        }

        if (unit && this->radian) {
            double temp = std::fmod(curInterger * 360.0 / (this->diameter * M_PI), 360.0);
            temp = std::round(temp * 10) / 10.0;
            tempText += QString(u8"(%1°)").arg(temp);
        }
    }

    return tempText;
}

double QRuleBar::getTofdTime(double depth)
{
    double retVal = 0;
    double hPCS = this->tofdPcs / 2;
    double v = this->pieceVelocity;
    const double t0 = wedgeDelay;

    double southPath = std::sqrt(depth * depth + hPCS * hPCS);
    retVal = southPath * 2 * 1000000 / (1000.0 * v) + 2 * t0;

    return retVal;
}

// need 工件纵波声速、PCS
bool QRuleBar::getTofdDepth(double timeUs, double &tofdDepth)
{
    bool ret = false;
    double PCS = this->tofdPcs;
    double v = this->pieceVelocity;
    const double t0 = wedgeDelay;

    double tempPos = ((timeUs - 2 * t0) * 1000.0 * v) / 1000000;
    double hPcs = PCS;

    if (std::fabs(tempPos - hPcs) < 0.0001) {
        tofdDepth = 0;
    } else if (tempPos > hPcs) {
        tofdDepth = std::sqrt(tempPos * tempPos - hPcs * hPcs) / 2;
        ret = true;
    }

    return ret;
}

void QRuleBar::drawTicker(QPainter *painter)
{
    int width, height;
    int length = 0, ideal_length;
    int pos;
    double start, end, cur;
    char unit_str[32];
    QString unitStr;
    size_t text_size;

    // 换算单位
    double local_lower = m_lower;
    double local_upper = m_upper;

    if (m_unit == "in") {
        local_lower *= 0.03937;
        local_upper *= 0.03937;
    }

    double increment; /* Number of pixels per unit 一个单位(mm etc)增加多少像素 */
    double lower = local_lower, upper = local_upper; /* Upper and lower limits, in ruler units */
    uint32_t scale; /* Number of units per major unit 每相邻的2个大刻度直接按相差多少单位(mm etc) */
    double max_size = m_maxsize;
    SPRulerMetric ruler_metric = ruler_metric_general; /* The metric to use for this unit system */
    bool unit_mark = false;

    QRect allocation = this->rect();

    QFontMetrics fm(font());
    int digit_height = fm.height(); // 字体高度

    if (m_show_direction == Bottom_Ruler || m_show_direction == Top_Ruler) {
        width = allocation.width();
        height = allocation.height();
    } else {
        width = allocation.height();
        height = allocation.width();
    }

    // 交换upper lower
    // right_ruler 交换!

    if ((rotateNo == RotateType::R90 && m_direction == Left_Ruler) || (rotateNo == RotateType::R180)
        || (rotateNo == RotateType::R270 && m_direction == Bottom_Ruler)) {
        lower = m_upper;
        upper = local_lower;
    }

    QImage image(width, height, QImage::Format_ARGB32);
    image.fill(m_faceColor);

    uint32_t *imageData = reinterpret_cast<uint32_t *>(image.scanLine(0));
    for (int i = 0; i < image.width(); i++) {
        imageData[i] = 0xFF000000;
    }
    imageData = reinterpret_cast<uint32_t *>(image.scanLine(height - 1));
    for (int i = 0; i < image.width(); i++) {
        imageData[i] = 0xFF000000;
    }

    QPainter painterImage(&image);
    QFont font = painterImage.font();
    // font.setBold(true);
    font.setFamily("Open Sans Regular");
    font.setPixelSize(14);
    QPen penTemp = painterImage.pen();
    penTemp.setColor(0x333333);
    painterImage.setPen(penTemp);
    painterImage.setFont(font);

    drawZoomSign(&painterImage, width, height);

    if (fabs(upper - lower) < DBL_EPSILON)
        return;

    increment = width / (upper - lower);

    scale = static_cast<uint32_t>(ceil(std::fabs(max_size)));
    sprintf(unit_str, "%u", scale);
    text_size = strlen(unit_str) * static_cast<uint32_t>(digit_height) + 10;
    if (text_size < 40)
        text_size = 40;

    for (scale = 0; scale < sizeof(ruler_metric.ruler_scale) / sizeof(ruler_metric.ruler_scale[0]);
         scale++)
        if (ruler_metric.ruler_scale[scale] * fabs(increment) > 1 * text_size)
            break;
    if (scale == sizeof(ruler_metric.ruler_scale) / sizeof(ruler_metric.ruler_scale[0]))
        scale = sizeof(ruler_metric.ruler_scale) / sizeof(ruler_metric.ruler_scale[0]) - 1;

    m_VGridInfo.clear();

    for (int i = sizeof(ruler_metric.subdivide) / sizeof(ruler_metric.subdivide[0]) - 1; i >= 0;
         i--) {
        double subd_incr;
        subd_incr = (ruler_metric.ruler_scale[scale] / ruler_metric.subdivide[i]);
        if (subd_incr * fabs(increment) <= MINIMUM_INCR)
            continue;

        if (i == 0)
            ideal_length = height / (1 * (i + 1)) - 6;
        else if (i == 1)
            ideal_length = height / (2 * (i + 1));
        else
            ideal_length = height / (2 * (i + 1)) - 2;

        if (ideal_length > ++length)
            length = ideal_length;
        // 确保刻度值都在显示是范围之内
        if (lower < upper) {
            start = ceil(lower / subd_incr) * subd_incr;
            end = floor(upper / subd_incr) * subd_incr;
        } else {
            start = ceil(upper / subd_incr) * subd_incr;
            end = floor(lower / subd_incr) * subd_incr;
        }

        int xCnt = static_cast<int>((end - start) / subd_incr);

        // for (cur = start; cur <= end; cur += subd_incr) {
        for (int j = 0; j <= xCnt; j++) {
            cur = j * subd_incr + start;
            pos = int(qRound((cur - lower) * increment + 1e-12));

            if (i == 2) { /* 排除重复的刻度 */
                int cnt = static_cast<int>((cur / subd_incr) + ((cur > 0) ? 0.5 : -0.5));
                if ((cnt % 5) == 0) {
                    continue;
                }

            } else if (i == 1) { /* 排除重复的刻度 */
                int cnt = static_cast<int>((cur / subd_incr) + ((cur > 0) ? 0.5 : -0.5));
                if ((cnt % 2) == 0)
                    continue;
            }

            QRect rt(pos, 1, 1, length);
            painterImage.drawLine(rt.topLeft(), rt.bottomLeft());

            // 绘制刻度数值
            do {
                if (i != 0) // i==0 需要绘制数字
                    break;

                if (pos < 0)
                    break;

                double val = pos * 1.0 / width;
                if ((val < 1) && (val > 0)
                    && (this->m_direction == QRulerPos::Left_Ruler
                        || this->m_direction == QRulerPos::Bottom_Ruler)) {
                    m_VGridInfo.push_back(val);
                }

                int tmpPos = pos;

                if ((width - tmpPos) < static_cast<int>(text_size)) // 超出范围
                    break;

                unitStr = getTickText(cur, static_cast<int>(scale), unit_mark);

                if (!unit_mark) {
                    unitStr += m_unit;
                    unit_mark = true;
                }

                int w = fm.horizontalAdvance(unitStr) * 4;

                if (!unitStr.isEmpty() && !unitStr.isNull())
                    painterImage.drawText(pos + 2, 0 + RULER_SIZE / 2 - 1, w, RULER_SIZE,
                                          Qt::AlignLeft | Qt::AlignTop, unitStr);

            } while (0);
        }
    }

    // drawGatePos(&painterImage, image.rect());

    if (this->m_show_direction == QRulerPos::Left_Ruler) {
        QImage imageT = image.transformed(/*rotateForm **/ QRuleBar::gRotateForm90);
        painter->drawImage(allocation, imageT);
    } else if (this->m_show_direction == QRulerPos::Right_Ruler2
               || this->m_show_direction == QRulerPos::Right_Ruler1) {
        QImage imageT = image.transformed(/*rotateForm **/ QRuleBar::gRotateForm270);
        painter->drawImage(allocation, imageT);
    } else {
        painter->drawImage(allocation, image);
    }

    if ((!m_VGridInfo.isEmpty()) && (this->m_enable)) {
        emit signalRefeshGrid(m_VGridInfo, (this->m_direction == Bottom_Ruler));
    }
}

void QRuleBar::drawTofdTicker(QPainter *painter)
{
    struct tofdTickInfo
    {
        double tickValue; // 深度值
        double tickPos;   // 百分比(在整个刻度尺上的百分比)
        bool flag = false;
    };
    QVector<tofdTickInfo> tickInfo;

    double ratio = 1;
    double ratio1 = 1;
    if (m_unit == "in") {
        ratio = 0.03937;
        ratio1 = 25.4;
    }

    // 换算单位
    double local_lower = m_lower;
    double local_upper = m_upper;

    // 反向计算 算出0位，然后计算出最大值
    double zeroPos = getTofdTime(0);
    double tickTimeMin = 0;   // 最小深度
    double tickTimeMax = 100; // 最大深度
    getTofdDepth(zeroPos, tickTimeMin);
    getTofdDepth(m_upper, tickTimeMax);

    tickTimeMin *= ratio;
    tickTimeMax *= ratio;

    QRect allocation = this->rect();
    QFontMetrics fm(font());
    int width, height;
    if (m_show_direction == Bottom_Ruler || m_show_direction == Top_Ruler) {
        width = allocation.width();
        height = allocation.height();
    } else {
        width = allocation.height();
        height = allocation.width();
    }

    bool reverseFlag = false;
    if ((rotateNo == RotateType::R90 && m_direction == Left_Ruler) || (rotateNo == RotateType::R180)
        || (rotateNo == RotateType::R270 && m_direction == Bottom_Ruler)) {
        reverseFlag = true;
    }

    int w = 4 * fm.horizontalAdvance(QString("%1").arg(std::ceil(tickTimeMax)));
    int effectWidth = width;
    if (zeroPos > local_lower)
        effectWidth = static_cast<int>(width * (local_upper - zeroPos) / (local_upper - local_lower));

    int maxTickCnt = effectWidth / w;
    double range = tickTimeMax - tickTimeMin;
    double step = -1;

    auto it =
        std::find_if(&ruler_metric_general.ruler_scale[0], &ruler_metric_general.ruler_scale[19],
                     [&](const double &v) { return (range / v) < maxTickCnt; });
    if (it != &ruler_metric_general.ruler_scale[19]) {
        step = *it;
    }

    if (step < 0)
        return;

    int l = 0;
    do {
        double d = tickTimeMin + l * step;
        if (d > tickTimeMax)
            break;
        double t = getTofdTime(d * ratio1);
        if (reverseFlag)
            tickInfo.append({ d, 1 - (t - local_lower) / (local_upper - local_lower), true });
        else
            tickInfo.append({ d, (t - local_lower) / (local_upper - local_lower), true });
        l++;
    } while (true);

    QImage image(width, height, QImage::Format_ARGB32);
    image.fill(m_faceColor);

    uint32_t *imageData = reinterpret_cast<uint32_t *>(image.scanLine(0));
    for (int i = 0; i < image.width(); i++) {
        imageData[i] = 0xFF000000;
    }
    imageData = reinterpret_cast<uint32_t *>(image.scanLine(height - 1));
    for (int i = 0; i < image.width(); i++) {
        imageData[i] = 0xFF000000;
    }

    QPainter painterImage(&image);
    QFont font = painterImage.font();
    // font.setBold(true);
    font.setFamily("Open Sans Regular");
    font.setPixelSize(14);
    QPen penTemp = painterImage.pen();
    penTemp.setColor(0x333333);
    painterImage.setPen(penTemp);
    painterImage.setFont(font);
    painterImage.setRenderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform, true);

    drawZoomSign(&painterImage, width, height);

    bool unitFlag = false;
    int tickCnt1;
    double step1;

    for (int k = 0; k < tickInfo.size(); k++) {
        QRect rt(static_cast<int>(tickInfo.at(k).tickPos * width), 0, 1, height * 3 / 4);
        painterImage.drawLine(rt.topLeft(), rt.bottomLeft());

        if ((k == 0) && (tickInfo.size() > 1)) {
            auto tempDis = std::fabs(tickInfo[0].tickPos - tickInfo[1].tickPos) * width;
            if (tempDis < 30) {
                tickCnt1 = 5;
                step1 = step / tickCnt1;
            } else {
                tickCnt1 = 10;
                step1 = step / tickCnt1;
            }
        } else {
            tickCnt1 = 10;
            step1 = step / tickCnt1;
        }

        // 绘制区间刻度尺
        for (int i = 1; i < tickCnt1; i++) {
            double d = tickInfo.at(k).tickValue + i * step1;
            double t = getTofdTime(d * ratio1);
            double p = (t - local_lower) / (local_upper - local_lower);
            if (p > 0.99)
                break;
            QRect rt1(static_cast<int>(p * width), 0, 1, height / 4);
            painterImage.drawLine(rt1.topLeft(), rt1.bottomLeft());
        }

        if (!unitFlag && (tickCnt1 == 10)) {
            unitFlag = true;
            painterImage.drawText(rt.left() + 2, 0 + RULER_SIZE / 2 - 1, w, RULER_SIZE,
                                  Qt::AlignLeft | Qt::AlignTop,
                                  QString::number(tickInfo.at(k).tickValue) + m_unit);
        } else
            painterImage.drawText(rt.left() + 2, 0 + RULER_SIZE / 2 - 1, w, RULER_SIZE,
                                  Qt::AlignLeft | Qt::AlignTop,
                                  QString::number(tickInfo.at(k).tickValue));
    }

    if (this->m_show_direction == QRulerPos::Left_Ruler) {
        QImage imageT = image.transformed(QRuleBar::gRotateForm90);
        painter->drawImage(allocation, imageT);
    } else {
        painter->drawImage(allocation, image);
    }

    if ((!m_VGridInfo.isEmpty()) && (this->m_enable)) {
        emit signalRefeshGrid(m_VGridInfo, (this->m_direction == Bottom_Ruler));
    }
}

/* 绘制当前鼠标在刻度值上的映射 */
void QRuleBar::drawGatePos(QPainter *painter, const QRect &rect)
{
    QRect allocation = rect; // this->rect();
    QImage img[] = {
        QImage("://images/scan-icon/gateA.png"), //.scaled(16, 16),
        QImage("://images/scan-icon/gateB.png"), //.scaled(16, 16),
        QImage("://images/scan-icon/gateI.png"), //.scaled(16, 16),
        QImage("://images/scan-icon/gateI.png"), //.scaled(16, 16),
    };

    // 交换upper lower
    bool reverse1 = false;
    bool reverse2 = false;
    if (((rotateNo == RotateType::R90) || (rotateNo == RotateType::R270))
        && (m_type == Depth_Ruler || m_type == SoundPath_Ruler)) {
        reverse1 = true;
    }
    if (((rotateNo == RotateType::R0) || (rotateNo == RotateType::R270))
        && (m_type == Height_Ruler)) {
        reverse2 = true;
    }

    /// 闸门从1开始
    for (auto gateId = 1; gateId < maxGateCnt; gateId++) {
        if (m_type == Height_Ruler && m_GateEnable[gateId]) {
            QImage imgh = QImage("://images/scan-icon/arrow_up.png").scaled(16, 16);
            if (reverse2)
                painter->drawImage(allocation.width() * (100 - m_GateHeight[gateId]) / 100 - 8, 4,
                                   imgh);
            else
                painter->drawImage(allocation.width() * m_GateHeight[gateId] / 100 - 8, 4, imgh);
        } else if ((m_type == Depth_Ruler || m_type == SoundPath_Ruler) && m_GateEnable[gateId]) {
            if (reverse1) {
                painter->drawImage(allocation.width() * (100 - m_GateMark1[gateId]) / 100 - 8, 4,
                                   img[gateId - 1]);
                painter->drawImage(allocation.width() * (100 - m_GateMark2[gateId]) / 100 - 8, 4,
                                   img[gateId - 1]);
            } else {
                painter->drawImage(allocation.width() * m_GateMark1[gateId] / 100 - 8, 4,
                                   img[gateId - 1]);
                painter->drawImage(allocation.width() * m_GateMark2[gateId] / 100 - 8, 4,
                                   img[gateId - 1]);
            }
        }
    }
}

void QRuleBar::drawZoomSign(QPainter *painter, int w, int h)
{
    if (!zoomEnable)
        return;

    // if (this->m_type != QRulerType::Depth_Ruler)
    //     return;

    int width, height;
    QRect allocation = QRect(0, 0, w, h);
    width = allocation.width();
    height = allocation.height();

    painter->save();

    QPen itemPen;
    itemPen.setColor(QColor(0x0, 0x0, 0x0, 0));
    itemPen.setStyle(Qt::NoPen);

    painter->setBrush(QBrush(QColor(0x20, 0x20, 0x20, 128)));

    painter->setPen(itemPen);
    QRect rect1(allocation);

    if (isMirror()) {
        // 反转过来显示
        rect1.setTop(allocation.top() + 2);
        rect1.setBottom(allocation.top() + height / 2 - 4);
        rect1.setLeft(allocation.left() + static_cast<int>((1 - this->zoomEnd) * width / 1.0) - 1);
        rect1.setRight(allocation.left() + static_cast<int>((1 - this->zoomStart) * width / 1.0) + 1);
    } else {
        rect1.setTop(allocation.top() + 2);
        rect1.setBottom(allocation.top() + height / 2 - 4);
        rect1.setLeft(allocation.left() + static_cast<int>(this->zoomStart * width / 1.0) + 1);
        rect1.setRight(allocation.left() + static_cast<int>(this->zoomEnd * width / 1.0) - 1);
    }

    painter->drawRoundedRect(rect1, 7, 7);

    painter->restore();
}

void QRuleBar::mousePressEvent(QMouseEvent *event)
{
    if (!zoomEnable) {
        QWidget::mousePressEvent(event);
        return;
    }

    zooming = true;
    moveType = MoveType::None;
    int cur = event->pos().y();
    int range = this->rect().height();
    if (this->m_show_direction == QRulerPos::Bottom_Ruler
        || this->m_show_direction == QRulerPos::Top_Ruler) {
        cur = event->pos().x();
        range = this->rect().width();
    }

    // 竖状刻度尺
    double currentPos = cur * 1.0 / range;
    if (isMirror() || this->m_show_direction == QRulerPos::Right_Ruler2) {
        currentPos = 1 - currentPos;
        cur = static_cast<int>(currentPos * range);
    }

    this->moveBeginPos = currentPos;
    this->lastZoomStart = this->zoomStart;
    this->lastZoomEnd = this->zoomEnd;

    int startPos = static_cast<int>(this->zoomStart * range);
    int endPos = static_cast<int>(this->zoomEnd * range);

    if (cur >= (startPos - 5) && cur <= (endPos + 5)) {
        if (std::abs(cur - startPos) < 5)
            moveType = MoveType::MoveBegin;
        else if (std::abs(cur - endPos) < 5)
            moveType = MoveType::MoveEnd;
        else
            moveType = MoveType::Move;
    }
    QWidget::mousePressEvent(event);
}

void QRuleBar::mouseMoveEvent(QMouseEvent *event)
{
    bool updateMark = false;
    if (!zoomEnable) {
        QWidget::mouseMoveEvent(event);
        return;
    }

    if (moveType != MoveType::None) {
        int cur = event->pos().y();
        int range = this->rect().height();
        if (this->m_show_direction == QRulerPos::Bottom_Ruler
            || this->m_show_direction == QRulerPos::Top_Ruler) {
            cur = event->pos().x();
            range = this->rect().width();
        }

        double currentPos = cur * 1.0 / range;
        double &start = this->zoomStart;
        double &end = this->zoomEnd;
        const double &lastStart = this->lastZoomStart;
        const double &lastEnd = this->lastZoomEnd;

        if (isMirror() || this->m_show_direction == QRulerPos::Right_Ruler2) {
            currentPos = 1 - currentPos;
        }
        double offset = currentPos - moveBeginPos;

        if (fabs(offset) < 0.003)
            return;

        switch (moveType) {
        case MoveType::MoveBegin:
            if (currentPos < (lastEnd - 0.01) && currentPos > 0) {
                start = currentPos;
                updateMark = true;
            }
            break;
        case MoveType::MoveEnd:
            if (currentPos > (lastStart + 0.01) && currentPos < 1) {
                end = currentPos;
                updateMark = true;
            }
            break;
        case MoveType::Move:
            if (offset < 0) {
                if (fabs(offset) > lastStart) {
                    offset = -lastStart;
                }
            } else {
                if (fabs(offset) > (1.0 - lastEnd)) {
                    offset = 1.0 - lastEnd;
                }
            }
            start = lastStart + offset;
            end = lastEnd + offset;
            updateMark = true;
            break;
        default:
            break;
        }
    }

    if (updateMark) {
        /// this->update();
        emit signalZoomChanged(this->zoomStart, this->zoomEnd);
    }

    QWidget::mouseMoveEvent(event);
}

void QRuleBar::mouseReleaseEvent(QMouseEvent *event)
{
    if (!zoomEnable) {
        QWidget::mousePressEvent(event);
        return;
    }

    if (moveType != MoveType::None) {
        emit signalZoomFinished();
    }

    zooming = false;
    QWidget::mouseReleaseEvent(event);
}

void QRuleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    if (zoomEnable
        && (fabs(this->zoomStart) > DBL_EPSILON || fabs(this->zoomEnd - 1.0) > DBL_EPSILON)) {
        this->zoomStart = 0.0;
        this->zoomEnd = 1.0;
        this->update();
        emit signalZoomChanged(this->zoomStart, this->zoomEnd);
    }

    if (this->m_direction == QRulerPos::Right_Ruler1) {
        emit signalPopPalette();
    }
    QWidget::mouseDoubleClickEvent(event);
}

bool QRuleBar::isMirror()
{
    if ((m_direction == QRulerPos::Bottom_Ruler
         && (rotateNo == RotateType::R180 || rotateNo == RotateType::R270))
        || (m_direction == QRulerPos::Left_Ruler
            && (rotateNo == RotateType::R90 || rotateNo == RotateType::R180)))
        return true;

    return false;
}

}
